package com.zxq.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sun.jmx.snmp.tasks.Task;
import com.zxq.exchange.enums.EProtocol;
import com.zxq.exchange.enums.ETcpFrame;
import com.zxq.exchange.model.ExchangeDTO;
import com.zxq.tcp.TcpNetty;
import com.zxq.web.dto.PlatformCmdDTO;
import com.zxq.web.dto.PlatformProductDTO;
import com.zxq.web.entity.IotProductDo;
import com.zxq.web.entity.IotProductFrameDo;
import com.zxq.web.enums.ECodeEnum;
import com.zxq.web.enums.EProductState;
import com.zxq.web.factory.TCPDispatchHandlerFactory;
import com.zxq.web.service.ITransformService;
import com.zxq.web.service.impl.ITransformServiceImpl;
import com.zxq.web.service.impl.IotFrameDoServiceImpl;
import com.zxq.web.service.impl.IotProductDoServiceImpl;
import com.zxq.web.service.impl.IotProductFrameDoServiceImpl;
import com.zxq.web.vo.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

@RestController("zxqReallyGood/")
@Slf4j
public class IOTPoemController {



    @Autowired
    ITransformServiceImpl iTransformService;

    @Autowired
    IotProductDoServiceImpl iotProductDoService;

    @Autowired
    IotFrameDoServiceImpl iotFrameDoService;

    @Autowired
    IotProductFrameDoServiceImpl iotProductFrameDoService;





    @PostMapping("platform/cmd")
    public ResultVO<PlatformCmdDTO> platformCmd(@RequestBody PlatformCmdDTO platformCmdDTO) {
        ResultVO<PlatformCmdDTO> resultVO = new ResultVO<>();
        ExchangeDTO exchangeDTO = iTransformService.platTransform(platformCmdDTO);
        //需要转换操作，暂时不动
        PlatformCmdDTO resultDTO = iTransformService.devTransform(exchangeDTO);
        if(resultDTO != null) {
            resultVO.setData(resultDTO);
            resultVO.setCode(200);
            resultVO.setMessage("success");
            resultVO.setSuccess(true);
        }
        return resultVO;
    }

    /**
     * netty保存产品id，和task任务的接口
     */
    ConcurrentHashMap<Long, Task> nettyTask = new ConcurrentHashMap<>();
    ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(2);

    @PostMapping("startOver/product")
    public ResultVO<String> startProductServer(PlatformProductDTO platformProductDTO) {

        Long productId  = platformProductDTO.getProductId();
        ResultVO<String> resultVO = new ResultVO<>();
        IotProductDo iotProductDo = iotProductDoService.getById(platformProductDTO.getProductId());
        IotProductDo queryCondition = new IotProductDo();
        queryCondition.setTransferPort(iotProductDo.getTransferPort());
        QueryWrapper<IotProductDo> queryWrapper = new QueryWrapper<>(queryCondition);
        Boolean existTcpServer = iotProductDoService.list(queryWrapper).size() > 0;
        if(existTcpServer) {
            resultVO.setSuccess(false);
            resultVO.setCode(ECodeEnum.ProductPortAlreadyUse.getCode());
            resultVO.setMessage(ECodeEnum.ProductPortAlreadyUse.getMsg());
            resultVO.setData(iotProductDo.getName());
            return resultVO;
        }

        Long operatorId  = platformProductDTO.getOperatorId();
        if(iotProductDo.getCreator() != operatorId) {
            resultVO.setSuccess(false);
            resultVO.setCode(ECodeEnum.UserNoPermission.getCode());
            resultVO.setMessage(ECodeEnum.UserNoPermission.getMsg());
            resultVO.setData(iotProductDo.getName());
            return resultVO;

        }

        switch (EProductState.getType(iotProductDo.getState())) {
            case alreadyPay:
            case stop:
                {
                Integer port = iotProductDo.getTransferPort();
                Integer protocol = iotProductDo.getProtocolFamilyId().intValue();
                EProtocol eProtocol = EProtocol.getType(protocol);
                switch (eProtocol) {
                    case TCP:{
                        TcpNetty tcpNetty = new TcpNetty(port);
                        //需要添加分发逻辑
                        IotProductFrameDo iotProductFrameDo = new IotProductFrameDo();
                        iotProductFrameDo.setProductId(iotProductDo.getId());
                        QueryWrapper<IotProductFrameDo> doQueryWrapper = new QueryWrapper<>(iotProductFrameDo);
                        List<IotProductFrameDo> iotProductFrameDoList = iotProductFrameDoService.list(doQueryWrapper);
                        iotProductFrameDoList.forEach(item -> {
                            ETcpFrame eTcpFrame = ETcpFrame.getType(item.getProtocolId().intValue());
                            tcpNetty.addHandler(TCPDispatchHandlerFactory.create(eTcpFrame));
                        });
                        nettyTask.put(productId, tcpNetty);
                        executorService.execute(tcpNetty);
                        log.info(String.format("operation:{0} start product {1} ",operatorId,productId));
                    }
                      break;
                    case UDP: {

                    }
                    break;
                    case MQTT:{

                    }
                    break;
                }
                iotProductDo.setStartTime(new Date());
                iotProductDo.setState(EProductState.run.getValue());
                iotProductDoService.updateById(iotProductDo);
                resultVO.setSuccess(true);
                resultVO.setCode(ECodeEnum.Success.getCode());
                resultVO.setMessage(ECodeEnum.Success.getMsg());
                resultVO.setData(iotProductDo.getName());
            }
            break;
            case run: {
                resultVO.setSuccess(false);
                resultVO.setCode(ECodeEnum.ProductAlreadyRun.getCode());
                resultVO.setMessage(ECodeEnum.ProductAlreadyRun.getMsg());
                resultVO.setData(iotProductDo.getName());
            }
            break;
            case noPay:{
                resultVO.setSuccess(false);
                resultVO.setCode(ECodeEnum.ProductNoPay.getCode());
                resultVO.setMessage(ECodeEnum.ProductNoPay.getMsg());
                resultVO.setData(iotProductDo.getName());
            }
            break;
            case expire:{
                resultVO.setSuccess(false);
                resultVO.setCode(ECodeEnum.ProductExpire.getCode());
                resultVO.setMessage(ECodeEnum.ProductExpire.getMsg());
                resultVO.setData(iotProductDo.getName());
            }
            break;
        }
        return resultVO;
    }





    @PostMapping("stop/product")
    public ResultVO<String> stopProductServer(PlatformProductDTO platformProductDTO) {
        Long productId = platformProductDTO.getProductId();
        Task task = nettyTask.get(productId);
        ResultVO<String> resultVO = new ResultVO<>();
        if(task == null) {
            resultVO.setSuccess(false);
            resultVO.setCode(ECodeEnum.ProductNoRunTask.getCode());
            resultVO.setMessage(ECodeEnum.ProductNoRunTask.getMsg());
            return resultVO;
        }
        IotProductDo iotProductDo = iotProductDoService.getById(productId);
        Long operatorId  = platformProductDTO.getOperatorId();
        if(iotProductDo.getCreator() != operatorId) {
            resultVO.setSuccess(false);
            resultVO.setCode(ECodeEnum.UserNoPermission.getCode());
            resultVO.setMessage(ECodeEnum.UserNoPermission.getMsg());
            resultVO.setData(iotProductDo.getName());
            return resultVO;
        }

        switch (EProductState.getType(iotProductDo.getState())) {
            case run:{
                task.cancel();
                resultVO.setSuccess(true);
                resultVO.setCode(ECodeEnum.ProductRunStop.getCode());
                resultVO.setMessage(ECodeEnum.ProductRunStop.getMsg());
                resultVO.setData(iotProductDo.getName());
                iotProductDo.setState(EProductState.stop.getValue());
                iotProductDoService.updateById(iotProductDo);
                nettyTask.remove(productId);
            }
            break;
            default:{
                resultVO.setSuccess(true);
                resultVO.setCode(ECodeEnum.ProductRunStop.getCode());
                resultVO.setMessage(ECodeEnum.ProductRunStop.getMsg());
                resultVO.setData(iotProductDo.getName());
            }
            break;
        }
        return resultVO;
    }
















}
